//-----------------------------------------------------------
//
//-----------------------------------------------------------
class FleshpoundZombieControllerTmp extends SRMonsterController;

var     float       RageAnimTimeout;    // How long until the RageAnim is completed; Hack so the server doesn't get stuck in idle when its doing the Rage anim
var		bool		bDoneSpottedCheck;
var     float       RageFrustrationTimer;       // Tracks how long we have been walking toward a visible enemy
var     float       RageFrustrationThreshhold;  // Base value for how long the FP should walk torward an enemy without reaching them before getting frustrated and raging

state ZombieHunt
{
	event SeePlayer(Pawn SeenPlayer)
	{
		if ( !bDoneSpottedCheck && PlayerController(SeenPlayer.Controller) != none )
		{
			if(KFGameType(Level.Game)==none && SRGameType(Level.Game)!=none)
			{
				//Log("FleshpoundZombieController.SeePlayer None Error");
			}
			// 25% chance of first player to see this Fleshpound saying something
			if ( !KFGameType(Level.Game).bDidSpottedFleshpoundMessage && FRand() < 0.25 )
			{
				PlayerController(SeenPlayer.Controller).Speech('AUTO', 12, "");
				KFGameType(Level.Game).bDidSpottedFleshpoundMessage = true;
			}

			bDoneSpottedCheck = true;
		}

		Super.SeePlayer(SeenPlayer);
	}
}

state RangedAttack
{
ignores SeePlayer, HearNoise, Bump;

	function bool Stopped()
	{
		return true;
	}

	function CancelCampFor(Controller C)
	{
		DoTacticalMove();
	}

	function StopFiring()
	{
		Global.StopFiring();
		if ( bHasFired )
		{
			bHasFired = false;
			WhatToDoNext(32);
		}
	}

	function EnemyNotVisible()
	{
		//let attack animation complete
		WhatToDoNext(33);
	}

	function Timer()
	{
		if ( Monster(Pawn).PreferMelee() )
		{
			SetCombatTimer();
			StopFiring();
			WhatToDoNext(34);
		}
		else
			TimedFireWeaponAtEnemy();
	}

	function DoRangedAttackOn(Actor A)
	{
		Target = A;
		GotoState('RangedAttack');
	}

	function BeginState()
	{
		StopStartTime = Level.TimeSeconds;
		bHasFired = false;
		Pawn.Acceleration = vect(0,0,0); //stop
		if ( Target == None )
			Target = Enemy;
		if ( Target == None )
			log(GetHumanReadableName()$" no target in ranged attack");
	}

Begin:
	bHasFired = false;
	GoalString = "Ranged attack";
	Focus = Target;
	Sleep(0.0);
	if ( Enemy != None )
		CheckIfShouldCrouch(Pawn.Location,Enemy.Location, 1);
	if ( Target!=none && NeedToTurn(Target.Location) )
	{
		Focus = Target;
		FinishRotation();
	}
	bHasFired = true;
	if ( Target == Enemy )
		TimedFireWeaponAtEnemy();
	else if(Target!=none)
		FireWeaponAt(Target);
	Sleep(0.1);
	if ( Monster(Pawn).PreferMelee() || (Target == None) || (Target != Enemy) || Monster(Pawn).bBoss )
		WhatToDoNext(35);
	if ( Enemy != None )
		CheckIfShouldCrouch(Pawn.Location,Enemy.Location, 1);
	Focus = Target;
	Sleep(FMax(Monster(Pawn).RangedAttackTime(),0.2 + (0.5 + 0.5 * FRand()) * 0.4 * (7 - Skill)));
	WhatToDoNext(36);
	if ( bSoaking )
		SoakStop("STUCK IN RANGEDATTACK!");
}


function TimedFireWeaponAtEnemy()
{
	if ( (Enemy == None) || FireWeaponAt(Enemy) )
		SetCombatTimer();
	else
		SetTimer(0.01, True);
}

state SpinAttack
{
ignores EnemyNotVisible;

	// Don't do this in this state
	function GetOutOfTheWayOfShot(vector ShotDirection, vector ShotOrigin){}

	function DoSpinDamage()
	{
		local Actor A;

		//log("FLESHPOUND DOSPINDAMAGE!");
		foreach CollidingActors(class'Actor', A, (ZombieFleshpound(Pawn).MeleeRange * 1.5)+Pawn.CollisionRadius, Pawn.Location)
			ZombieFleshPound(Pawn).SpinDamage(A);
	}

Begin:

WaitForAnim:
	while( KFM.bShotAnim )
	{
		Sleep(0.1);
		DoSpinDamage();
	}

	WhatToDoNext(152);
	if ( bSoaking )
		SoakStop("STUCK IN SPINATTACK!!!");
}

state ZombieCharge
{
	function Tick( float Delta )
	{
		local ZombieFleshPound ZFP;
		Global.Tick(Delta);

		// Make the FP rage if we haven't reached our enemy after a certain amount of time
		if( RageFrustrationTimer < RageFrustrationThreshhold )
		{
			RageFrustrationTimer += Delta;

			if( RageFrustrationTimer >= RageFrustrationThreshhold )
			{
				ZFP = ZombieFleshPound(Pawn);

				if( ZFP != none && !ZFP.bChargingPlayer )
				{
					ZFP.StartCharging();
					ZFP.bFrustrated = true;
				}
			}
		}
	}


	function bool StrafeFromDamage(float Damage, class<DamageType> DamageType, bool bFindDest)
	{
		return false;
	}

	// I suspect this function causes bloats to get confused
	function bool TryStrafe(vector sideDir)
	{
		return false;
	}

	function Timer()
	{
		Disable('NotifyBump');
		Target = Enemy;
		TimedFireWeaponAtEnemy();
	}

	function BeginState()
	{
		Super.BeginState();

		RageFrustrationThreshhold = default.RageFrustrationThreshhold + (Frand() * 5);
		RageFrustrationTimer = 0;
	}

WaitForAnim:

	if ( Monster(Pawn).bShotAnim )
	{
		Goto('Moving');
	}
	if ( !FindBestPathToward(Enemy, false,true) )
		GotoState('ZombieRestFormation');
Moving:
	MoveToward(Enemy);
	WhatToDoNext(17);
	if ( bSoaking )
		SoakStop("STUCK IN CHARGING!");
}

// Used to set a timeout for the WaitForAnim state. This is a bit of a hack fix
// for the FleshPound getting stuck in its idle anim on a dedicated server when it
// is supposed to be raging. For some reason, on a dedicated server only, it
// never gets an animend call for the PoundRage anim, instead the anim gets
// interrupted by the PoundIdle anim. If we figure that bug out, we can
// probably take this out in the future. But for now the fix works - Ramm
function SetPoundRageTimout(float NewRageTimeOut)
{
	RageAnimTimeout = NewRageTimeOut;
}

state WaitForAnim
{
Ignores SeePlayer,HearNoise,Timer,EnemyNotVisible,NotifyBump;

	// Don't do this in this state
	function GetOutOfTheWayOfShot(vector ShotDirection, vector ShotOrigin){}

	function BeginState()
	{
		bUseFreezeHack = false;
	}

	// The rage anim has ended, clear the flags and let the AI do its thing
	function RageTimeout()
	{
		if( bUseFreezeHack )
		{
			if( Pawn!=None )
			{
				Pawn.AccelRate = Pawn.Default.AccelRate;
				Pawn.GroundSpeed = Pawn.Default.GroundSpeed;
			}
			bUseFreezeHack = false;
			AnimEnd(0);
		}
	}

	function Tick( float Delta )
	{
		Global.Tick(Delta);

		if( RageAnimTimeout > 0 )
		{
			RageAnimTimeout -= Delta;

			if( RageAnimTimeout <= 0 )
			{
				RageAnimTimeout = 0;
				RageTimeout();
			}
		}

		if( bUseFreezeHack )
		{
			MoveTarget = None;
			MoveTimer = -1;
			Pawn.Acceleration = vect(0,0,0);
			Pawn.GroundSpeed = 1;
			Pawn.AccelRate = 0;
		}
	}
	function EndState()
	{
		if( Pawn!=None )
		{
			Pawn.AccelRate = Pawn.Default.AccelRate;
			Pawn.GroundSpeed = Pawn.Default.GroundSpeed;
		}
		bUseFreezeHack = false;
	}

Begin:
	while( KFM.bShotAnim )
	{
		Sleep(0.15);
	}
	WhatToDoNext(99);
}

defaultproperties
{
     RageFrustrationThreshhold=10.000000
}
